;; Copyright (c) [2022] [bobwxc]
;; This file is licensed under Mulan PubL v2.
;; You can use this software according to the terms and conditions of the Mulan PubL v2.
;; You may obtain a copy of Mulan PubL v2 at:
;;          http://license.coscl.org.cn/MulanPubL-2.0
;; THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
;; EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
;; MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
;; See the Mulan PubL v2 for more details.


(in-package #:cl-mdb)

(defun random-string (len)
  (let ((ab #(#\_ #\- #\1 #\2 #\3 #\4 #\5 #\6 #\7 #\8 #\9 #\0 #\a #\b #\c #\d
              #\e #\f #\g #\h #\i #\j #\k #\l #\m #\n #\o #\p #\q #\r #\s #\t
              #\u #\v #\w #\x #\y #\z #\A #\B #\C #\D #\E #\F #\G #\H #\I #\J
              #\K #\L #\M #\N #\O #\P #\Q #\R #\S #\T #\U #\V #\W #\X #\Y #\Z)))
    (concatenate 'string (loop for i from 1 to len
                               collect(aref ab (random 64))))))

(defun test ()
  (let ((root-list (init-root-list))
        (key-list '()))

    (format t "==================================~%")
    (format t "CL-MDB Test~%")
    (format t "==================================~%")

    (format t " * insert test start...~%")
    (dotimes (i 1000)
      (insert root-list
              (let ((x (random-string (random 20)))) (push x key-list) x)
              (random-string (random 50))))
    (setf key-list (remove-duplicates key-list :test #'equal))
    (format t "   inserted ~D key~%" (length key-list))
    (format t "   inserted ~D value~%" (length (cadr root-list)))
    (if (= (length key-list) (length (cadr root-list)))
        (format t "   = OK~%")
      (format t " ! /= error~%"))
    (format t " * insert test completed.~%")


    (format t " * update test start...~%")
    (dotimes (i 500)
      (let ((k (nth (random (length key-list)) key-list))
            (s (random-string (random 50))))
        (update root-list k s)
        (when (not (equal (select root-list k) s))
          (format t " ! update test error: ~S | ~S | ~S~%" k s (select root-list k)))
        ))
    (format t " * update test completed.~%")

    (format t " * remov & gc test start...~%")
    (let ((a 0)
          (b 0)
          (c 0))
      (dotimes (i 500)
        (let ((k (nth (random (length key-list)) key-list)))
          (when (not (remov root-list k))
            (incf a))
          (when (not (equal (select root-list k) nil))
            (format t "remov & gc test error: ~S | ~S~%" k (select root-list k)))
          ))
      (setf b (length (cadr root-list)))
      (setf root-list (gbc root-list))
      (setf c (length (cadr root-list)))
      (if (= (+ a (- b c)) 500)
          (format t "   ~D - ~D + ~D = 500 OK~%" b c a)
        (format t " ! ~D - ~D + ~D /= 500 error~%" b c a))
      )
    (format t " * remov & gc test completed.~%")


    (format t " * mdump & mload test start...~%")
    (mdump root-list "./test.txt")
    (setf root-list (mload "./test.txt"))
    (setf (row-content (cadr (select-index (car root-list) (row-original-key (car (cadr root-list)))))) "test")
    (when (not (equal (row-content (car (cadr root-list))) "test"))
      (format t " ! mdump & mload test faild: ~S~%" (car (cadr root-list))))
    (format t " * mdump & mload test completed.~%")

    (format t "==================================~%")
    ))

